package com.cyy.util

import java.util.Optional
import java.util.TreeMap

class PropertyTree constructor(): TreeMap<String, Any>() {

    constructor(key: String, value: Any):this(){
        put(key, value)
    }
    fun appendBranchFromKeyValue(keyPath: List<String>, value: Any) {
        appendBranch(TreeBranchBuilder(keyPath, value).build())
    }

    fun appendBranch( branchTree:PropertyTree) {
        branchTree.forEach{
            (key, value) ->
            val removedBranch = removeMixedTypedBranch(key, value)
            merge(key, value) {
                root, branch -> resolveDuplicates(root as PropertyTree, branch as PropertyTree)
            }
            removedBranch.ifPresent(this::appendBranch)
        }
    }

    private fun removeMixedTypedBranch(key: String, value: Any): Optional<PropertyTree> {
        var removedBranch: PropertyTree? = null
        if (containsKey(key) && isTerminationNode(key, value)) {
            removedBranch = PropertyTree(key + flatKey(key), flatValue(key))
            remove(key)
        }
        return Optional.ofNullable(removedBranch)
    }
    private fun isTerminationNode(key: String, value: Any): Boolean {
        return !(get(key) is PropertyTree && value is PropertyTree)
    }
    private fun flatKey(tree: Any): String {
        if (tree is PropertyTree) {
            val next = getNext(tree)
            return "." + next.key + flatKey(next.value)
        } else {
            return ""
        }
    }
    private fun flatValue(tree: Any): Any {
        return if (tree is PropertyTree) {
            flatValue(getNext(tree).value)
        } else {
            tree
        }
    }
    fun getNext(tree: PropertyTree): Map.Entry<String, Any> {
        return tree.entries.iterator().next()
    }
    fun resolveDuplicates(root: PropertyTree, branch: PropertyTree): Any {
        root.appendBranch(branch)
        return root
    }
    fun toYAML(): String {
        return YamlPrinter(this).invoke()
    }
}
